package com.itheima.d2_reflect2;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 掌握反射第二步：通过反射获取类的成员：构造器、成员变量、成员方法
 */
public class ReflectDemo2 {
    /**
     * 1.获取构造器
     */
    @Test
    public void getConStructorInfo() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取类的字节码对象
        Class c = Student.class;
        //2.获取全部构造器对象 DeclaredConstructors(私有的也可访问)
        Constructor[] cons1 = c.getDeclaredConstructors();
        for (Constructor con : cons1) {
            System.out.println(con.getName()+"("+con.getParameterCount()+")");
        }
        //3.获取指定构造器对象
            //全参构造器
        Constructor con2 = c.getDeclaredConstructor(String.class, int.class, String.class);
        System.out.println(con2.getName()+"("+con2.getParameterCount()+")");
            //无参构造器
        Constructor con3 = c.getConstructor();
        System.out.println(con3.getName()+"("+con3.getParameterCount()+")");
        //4.通过构造器对象创建对象
        con2.setAccessible(true);//暴力反射
        Student s1 = (Student) con2.newInstance("蔡徐坤", 18, "打篮球");
        System.out.println(s1);

        Student s2 = (Student) con3.newInstance();
        System.out.println(s2);



    }

    /**
     * 2.获取类的成员变量
     */
    @Test
    public void getFieldInfo() throws Exception {
        //1.获取类的字节码对象
        Class<Student> c = Student.class;
        //2.获取全部成员变量对象
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName()+"("+field.getType()+")");
        }
        //3.获取指定成员变量对象
        Field name = c.getDeclaredField("name");
        System.out.println(name.getName()+"("+name.getType()+")");
        Field hobby = c.getDeclaredField("hobby");
        System.out.println(hobby.getName()+"("+hobby.getType()+")");

        //4.获取成员变量的目的依然是赋值和取值
        Student s = new Student();
        System.out.println(s);
        System.out.println("=============");
        name.set(s,"王源");
        //暴力反射
        hobby.setAccessible(true);
        hobby.set(s,"看电影");
        System.out.println(name.get(s));
        System.out.println(hobby.get(s));
        System.out.println(s);
    }

    /**
     * 3.获取类的成员方法
     */
    @Test
    public void getMethodInfo() throws Exception {
        //1.获取类的字节码对象
        Class<Student> c = Student.class;
        //2.获取全部成员方法对象
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+"("+method.getParameterCount()+")");
        }
        System.out.println("===================");
        //3.获取指定成员方法对象
        Method study  = c.getDeclaredMethod("study");
        Method eat = c.getDeclaredMethod("eat", String.class);
        System.out.println(study.getName()+"("+study.getParameterCount()+")");
        System.out.println(eat.getName()+"("+eat.getParameterCount()+")");

        //4.获取方法的目的依然是执行
        Student s = new Student();
        study.invoke(s);
        System.out.println("=============");
        eat.setAccessible(true);
        Object rs = eat.invoke( s,"屎");
        System.out.println( rs);
    }

}
